package be.music.tool.practice;

import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import be.music.tool.alert.Alert;
import be.music.tool.practice.PracticeEvent;
import be.music.tool.practice.PracticeRoutine;
import be.music.tool.time.Clock;
import be.music.tool.time.Time;

public class PracticeSession implements Observer{

	private PracticeRoutine practiceRoutine;
	private PracticeEvent activeEvent;
	private Iterator<Alert> alertIterator;
	private Alert pendingAlert;
	
	public PracticeSession(PracticeRoutine routine) {
		
		this.practiceRoutine = routine;
		
	}
	
	/**
	 * @return the practiceRoutine
	 */
	public PracticeRoutine getPracticeRoutine() {
		return practiceRoutine;
	}
	/**
	 * @param practiceRoutine the practiceRoutine to set
	 */
	public void setPracticeRoutine(PracticeRoutine practiceRoutine) {
		this.practiceRoutine = practiceRoutine;
	}

	private void performEventUpdate(Clock clock) {
		
		
		if(activeEvent == null || clock.getTime().isAfter(activeEvent.getEndTime())) {
			
			loadNextEvent(clock.getTime());
			
		}
		
		
	}
	
	private void loadNextEvent(Time time) {
		
		activeEvent = practiceRoutine.getPracticeEvent(time);
		
		if(activeEvent != null) {
			alertIterator = activeEvent.getAlertsIterator();
		}
		
	}
	
	private void performAlertUpdate(Clock clock) {
		//TODO: cleanup this code
		
		
		//If there is a pendingAlert that hasn't been triggered yet.
		if(pendingAlert != null && !pendingAlert.hasTriggered()) {
			
			if(clock.getTime().isAfterIncl(pendingAlert.getTime())) {
				pendingAlert.trigger();
				//TODO: Maybe the pendingAlert can be changed here?
			}
			
		//If there are more alerts
		}else if(alertIterator != null && alertIterator.hasNext()) {
			
			//There isn't a pendingAlert yet, or the current pendingAlert was already triggered.
			if(pendingAlert == null || pendingAlert.hasTriggered()) {
				
				//Retrieve the next alert.
				pendingAlert = alertIterator.next();
				
			}
			
		}
		
	}
	
	public PracticeEvent getActiveEvent() {
		return this.activeEvent;
	}
	
	@Override
	public void update(Observable o, Object arg) {
		if(o.getClass().equals(Clock.class)) {
			Clock clock = (Clock) o;
			performEventUpdate(clock);
			performAlertUpdate(clock);
		}
		
	}
	
}
